/**
 * @file sunnet.h
 * @author HaoyuWang (136046355@qq.com)
 * @brief c++仿写skynet，单例
 * @version 0.1
 * @date 2025-01-23
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#ifndef __SUNNET_H__
#define __SUNNET_H__

#include <vector>
#include <memory>
#include <thread>
#include <unordered_map>
#include <queue>

#include "worker.h"
#include "service.h"
#include "service_msg.h"
#include "common.h"
#include "socket_worker.h"
#include "conn.h"
#include "log.h"


class Sunnet
{
public:
    Sunnet();
    ~Sunnet();
    Sunnet(const Sunnet &) = delete;
    const Sunnet operator=(const Sunnet &) = delete;

    /**
     * @brief Get the Instance object
     * 
     * @return Sunnet& 
     */
    static Sunnet& GetInstance();

    /**
     * @brief 入口函数
     * 
     */
    void Start();

    void Wait();

    uint32_t NewService(std::shared_ptr<std::string> type);

    /**
     * @brief 只能由service自己调用，里面会调用service中的方法，线程不安全
     * 
     * @param id 
     */
    void KillService(uint32_t id);

    /**
     * @brief 向目的service发送msg
     * 
     * @param dest_id 目的service id
     * @param msg 
     */
    void Send(uint32_t dest_id, std::shared_ptr<BaseMsg> msg);

    /**
     * @brief 从global_queue中弹出一个需要处理msg的service
     * 
     * @return std::shared_ptr<Service> 
     */
    std::shared_ptr<Service> PopGlobalQueue();

    /**
     * @brief 将一个需要处理msg的service放进global_queue
     * 
     * @param srv 
     */
    void PushGlobalQueue(std::shared_ptr<Service> srv);

    /**
     * @brief 临时构造ServiceMsg
     * 
     * @param source 
     * @param buff 
     * @param len 
     * @return std::shared_ptr<ServiceMsg> 
     */
    std::shared_ptr<ServiceMsg> MakeMsg(uint32_t source, char* buff, int len);

    /**
     * @brief Send方法中调用
     * 
     */
    void CheckAndWeakUp();

    /**
     * @brief 当global_queue中没有srv时，工作线程调用该方法
     * 
     */

    /**
     * @brief Get the Service object
     * 
     * @param id service id
     * @return std::shared_ptr<Service> 
     */
    std::shared_ptr<Service> GetService(uint32_t id);

    void WorkerWait();

    int AddConn(int fd, uint32_t id, Conn::Type type);
    std::shared_ptr<Conn> GetConn(int fd);
    bool RemoveConn(int fd);

    int Listen(uint32_t port, uint32_t service_id);
    void CloseConn(uint32_t fd);
    void ModifyEvent(int fd, bool epoll_out);

    void SendMsg2LogService(std::shared_ptr<LogMsg> msg);

private:
    /**
     * @brief 开启工作线程
     * 
     */
    void StartWorker();
    void StartSocket();
    void StartLogService();

public:
    // 工作线程相关
    int worker_num_ = common::WORKER_NUM;
    std::vector<std::shared_ptr<Worker>> workers_vec_;
    std::vector<std::shared_ptr<std::thread>> worker_thread_vec_;
    pthread_mutex_t sleep_mutex_;
    pthread_cond_t sleep_cond_;
    int sleep_count_ = 0;

    // 网络线程相关
    std::shared_ptr<SocketWorker> socket_worker_;
    std::shared_ptr<std::thread> socket_thread_;

    // 连接相关
    std::unordered_map<uint32_t, std::shared_ptr<Conn>> conns_;
    pthread_rwlock_t conns_lock_;

    // 服务相关
    std::unordered_map<uint32_t, std::shared_ptr<Service>> service_map_;
    uint32_t max_id_ = 0;
    pthread_rwlock_t services_lock_;
    std::queue<std::shared_ptr<Service>> global_queue_;
    pthread_spinlock_t global_queue_lock_;

    // log相关
    uint32_t log_service_id_;
};


#endif  // __SUNNET_H__